/*
 *  Copyright 2011 yuxinlei.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package com.hudson.plugin.result.collector.server.datastore.internal.dao.impl;

import com.hudson.plugin.result.collector.server.datastore.dao.PromotionsEntityJpaController;
import com.hudson.plugin.result.collector.server.datastore.dao.exceptions.NonexistentEntityException;
import com.hudson.plugin.result.collector.server.datastore.dao.exceptions.PreexistingEntityException;
import com.hudson.plugin.result.collector.server.datastore.internal.entity.PromotionsEntity;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.EntityNotFoundException;
import com.hudson.plugin.result.collector.server.datastore.internal.entity.ProjectsEntity;
import com.hudson.plugin.result.collector.server.datastore.internal.entity.PromotionBuildsEntity;

import java.util.ArrayList;
import java.util.Collection;

/**
 *
 * @author yuxinlei
 */
public class PromotionsEntityJpaControllerImpl implements PromotionsEntityJpaController {

    public PromotionsEntityJpaControllerImpl() {
        emf = Persistence.createEntityManagerFactory("reportdb");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(PromotionsEntity promotionsEntity) throws PreexistingEntityException, Exception {
        if (promotionsEntity.getPromotionBuildsesById() == null) {
            promotionsEntity.setPromotionBuildsesById(new ArrayList<PromotionBuildsEntity>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            ProjectsEntity projectsByProjectId = promotionsEntity.getProjectsByProjectId();
            if (projectsByProjectId != null) {
                projectsByProjectId = em.getReference(projectsByProjectId.getClass(), projectsByProjectId.getId());
                promotionsEntity.setProjectsByProjectId(projectsByProjectId);
            }
            Collection<PromotionBuildsEntity> attachedPromotionBuildsesById = new ArrayList<PromotionBuildsEntity>();
            for (PromotionBuildsEntity promotionBuildsesByIdPromotionBuildsEntityToAttach : promotionsEntity.getPromotionBuildsesById()) {
                promotionBuildsesByIdPromotionBuildsEntityToAttach = em.getReference(promotionBuildsesByIdPromotionBuildsEntityToAttach.getClass(), promotionBuildsesByIdPromotionBuildsEntityToAttach.getId());
                attachedPromotionBuildsesById.add(promotionBuildsesByIdPromotionBuildsEntityToAttach);
            }
            promotionsEntity.setPromotionBuildsesById(attachedPromotionBuildsesById);
            em.persist(promotionsEntity);
            if (projectsByProjectId != null) {
                projectsByProjectId.getPromotionsesById().add(promotionsEntity);
                projectsByProjectId = em.merge(projectsByProjectId);
            }
            for (PromotionBuildsEntity promotionBuildsesByIdPromotionBuildsEntity : promotionsEntity.getPromotionBuildsesById()) {
                PromotionsEntity oldPromotionsByPromotionIdOfPromotionBuildsesByIdPromotionBuildsEntity = promotionBuildsesByIdPromotionBuildsEntity.getPromotionsByPromotionId();
                promotionBuildsesByIdPromotionBuildsEntity.setPromotionsByPromotionId(promotionsEntity);
                promotionBuildsesByIdPromotionBuildsEntity = em.merge(promotionBuildsesByIdPromotionBuildsEntity);
                if (oldPromotionsByPromotionIdOfPromotionBuildsesByIdPromotionBuildsEntity != null) {
                    oldPromotionsByPromotionIdOfPromotionBuildsesByIdPromotionBuildsEntity.getPromotionBuildsesById().remove(promotionBuildsesByIdPromotionBuildsEntity);
                    oldPromotionsByPromotionIdOfPromotionBuildsesByIdPromotionBuildsEntity = em.merge(oldPromotionsByPromotionIdOfPromotionBuildsesByIdPromotionBuildsEntity);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findPromotionsEntity(promotionsEntity.getId()) != null) {
                throw new PreexistingEntityException("PromotionsEntity " + promotionsEntity + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(PromotionsEntity promotionsEntity) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            PromotionsEntity persistentPromotionsEntity = em.find(PromotionsEntity.class, promotionsEntity.getId());
            ProjectsEntity projectsByProjectIdOld = persistentPromotionsEntity.getProjectsByProjectId();
            ProjectsEntity projectsByProjectIdNew = promotionsEntity.getProjectsByProjectId();
            Collection<PromotionBuildsEntity> promotionBuildsesByIdOld = persistentPromotionsEntity.getPromotionBuildsesById();
            Collection<PromotionBuildsEntity> promotionBuildsesByIdNew = promotionsEntity.getPromotionBuildsesById();
            if (projectsByProjectIdNew != null) {
                projectsByProjectIdNew = em.getReference(projectsByProjectIdNew.getClass(), projectsByProjectIdNew.getId());
                promotionsEntity.setProjectsByProjectId(projectsByProjectIdNew);
            }
            Collection<PromotionBuildsEntity> attachedPromotionBuildsesByIdNew = new ArrayList<PromotionBuildsEntity>();
            for (PromotionBuildsEntity promotionBuildsesByIdNewPromotionBuildsEntityToAttach : promotionBuildsesByIdNew) {
                promotionBuildsesByIdNewPromotionBuildsEntityToAttach = em.getReference(promotionBuildsesByIdNewPromotionBuildsEntityToAttach.getClass(), promotionBuildsesByIdNewPromotionBuildsEntityToAttach.getId());
                attachedPromotionBuildsesByIdNew.add(promotionBuildsesByIdNewPromotionBuildsEntityToAttach);
            }
            promotionBuildsesByIdNew = attachedPromotionBuildsesByIdNew;
            promotionsEntity.setPromotionBuildsesById(promotionBuildsesByIdNew);
            promotionsEntity = em.merge(promotionsEntity);
            if (projectsByProjectIdOld != null && !projectsByProjectIdOld.equals(projectsByProjectIdNew)) {
                projectsByProjectIdOld.getPromotionsesById().remove(promotionsEntity);
                projectsByProjectIdOld = em.merge(projectsByProjectIdOld);
            }
            if (projectsByProjectIdNew != null && !projectsByProjectIdNew.equals(projectsByProjectIdOld)) {
                projectsByProjectIdNew.getPromotionsesById().add(promotionsEntity);
                projectsByProjectIdNew = em.merge(projectsByProjectIdNew);
            }
            for (PromotionBuildsEntity promotionBuildsesByIdOldPromotionBuildsEntity : promotionBuildsesByIdOld) {
                if (!promotionBuildsesByIdNew.contains(promotionBuildsesByIdOldPromotionBuildsEntity)) {
                    promotionBuildsesByIdOldPromotionBuildsEntity.setPromotionsByPromotionId(null);
                    promotionBuildsesByIdOldPromotionBuildsEntity = em.merge(promotionBuildsesByIdOldPromotionBuildsEntity);
                }
            }
            for (PromotionBuildsEntity promotionBuildsesByIdNewPromotionBuildsEntity : promotionBuildsesByIdNew) {
                if (!promotionBuildsesByIdOld.contains(promotionBuildsesByIdNewPromotionBuildsEntity)) {
                    PromotionsEntity oldPromotionsByPromotionIdOfPromotionBuildsesByIdNewPromotionBuildsEntity = promotionBuildsesByIdNewPromotionBuildsEntity.getPromotionsByPromotionId();
                    promotionBuildsesByIdNewPromotionBuildsEntity.setPromotionsByPromotionId(promotionsEntity);
                    promotionBuildsesByIdNewPromotionBuildsEntity = em.merge(promotionBuildsesByIdNewPromotionBuildsEntity);
                    if (oldPromotionsByPromotionIdOfPromotionBuildsesByIdNewPromotionBuildsEntity != null && !oldPromotionsByPromotionIdOfPromotionBuildsesByIdNewPromotionBuildsEntity.equals(promotionsEntity)) {
                        oldPromotionsByPromotionIdOfPromotionBuildsesByIdNewPromotionBuildsEntity.getPromotionBuildsesById().remove(promotionBuildsesByIdNewPromotionBuildsEntity);
                        oldPromotionsByPromotionIdOfPromotionBuildsesByIdNewPromotionBuildsEntity = em.merge(oldPromotionsByPromotionIdOfPromotionBuildsesByIdNewPromotionBuildsEntity);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                int id = promotionsEntity.getId();
                if (findPromotionsEntity(id) == null) {
                    throw new NonexistentEntityException("The promotionsEntity with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(int id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            PromotionsEntity promotionsEntity;
            try {
                promotionsEntity = em.getReference(PromotionsEntity.class, id);
                promotionsEntity.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The promotionsEntity with id " + id + " no longer exists.", enfe);
            }
            ProjectsEntity projectsByProjectId = promotionsEntity.getProjectsByProjectId();
            if (projectsByProjectId != null) {
                projectsByProjectId.getPromotionsesById().remove(promotionsEntity);
                projectsByProjectId = em.merge(projectsByProjectId);
            }
            Collection<PromotionBuildsEntity> promotionBuildsesById = promotionsEntity.getPromotionBuildsesById();
            for (PromotionBuildsEntity promotionBuildsesByIdPromotionBuildsEntity : promotionBuildsesById) {
                promotionBuildsesByIdPromotionBuildsEntity.setPromotionsByPromotionId(null);
                promotionBuildsesByIdPromotionBuildsEntity = em.merge(promotionBuildsesByIdPromotionBuildsEntity);
            }
            em.remove(promotionsEntity);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public PromotionsEntity findPromotionsEntity(int id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(PromotionsEntity.class, id);
        } finally {
            em.close();
        }
    }
}
